home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / COMMUNIC / 0558.ZIP / SCANCODE.ASM < prev    next >
Assembly Source File  |  1987-05-01  |  18KB  |  590 lines

  1.     page    64,132
  2. COMMENT ;
  3.  
  4.     SCANCODE version 1.2 by Merlin R. Null 4-30-87
  5.     A simple table of scancodes in decimal and hex
  6.     for use in assembly language programming.
  7.     SCANCODE R causes the program to go memory
  8.     resident.  Without this switch, it is a normal
  9.     nonresident program.
  10.  
  11. ; 0 Black    4 Red          8 Gray        12 Light Red
  12. ; 1 Blue    5 Magenta     9 Light Blue    13 Light Magenta
  13. ; 2 Green    6 Brown         10 Light Green    14 Yellow
  14. ; 3 Cyan    7 White         11 Light Cyan    15 High-Intensity White
  15.  
  16. ;Set the following equates to values between 0 and 15 for foreground
  17. ;colors and between 0 and 7 for background colors.
  18. ;Select a number from 0 to 15 from the above chart.
  19.  
  20. FrameFgColor    EQU    15        ;frame foreground color
  21. FrameBgColor    EQU    4        ;frame background color
  22. ChartFgColor    EQU    0        ;chart foreground color
  23. ChartBgColor    EQU    3        ;chart background color
  24.  
  25. FrameColor    EQU    FrameFgColor + (FrameBgColor * 16)
  26. ChartColor    EQU    ChartFgColor + (ChartBgColor * 16)
  27.  
  28. ;Various Program Equates
  29.  
  30. MonoSegAddr    EQU    0B000h            ;address of monochrome buffer
  31. GraphSegAddr    EQU    0B800h            ;address of graphics buffer
  32.  
  33. ;--------------------------------------------------------------------
  34. Interrupts    SEGMENT AT 0h            ;interrupt table segment
  35.  
  36.         ORG    9h*4
  37.  
  38. KeyboardInt    DW    2 DUP (0)        ;interrupt 9 vector
  39.  
  40. Interrupts    ENDS
  41.  
  42. Code        SEGMENT PARA PUBLIC 'CODE'
  43.  
  44.         ASSUME CS:Code
  45.  
  46.         ORG    100h            ;COM format
  47.  
  48. Begin:        JMP    Initialize        ;goto initialization routine
  49.  
  50. DisplayTable    DB    2Dh,29h            ;display re-enable values for
  51.                         ; modes 2 and 3
  52. Video        DW    0B800h,0B900h        ;starting addresses of video
  53.         DW    0BA00h,0BB00h        ; memory for CGA pages 0 - 3
  54.         DW    0B000h            ;video segment address for
  55.                         ;monochrome
  56.  
  57. ScanData    DB    '╔════════════╤════════════╤════════════╤'
  58.         DB    '═════════════╗■'
  59.         DB    '║ KEY DEC HEX│ KEY DEC HEX│ KEY DEC HEX│'
  60.         DB    ' KEY  DEC HEX║■'
  61.         DB    '║ Aa  30  1E │ Vv  47  2F │ ,<  51  33 │'
  62.         DB    ' Rtrn 28  1C ║■'
  63.         DB    '║ Bb  48  30 │ Ww  17  11 │ .>  52  34 │'
  64.         DB    ' Alt  56  38 ║■'
  65.         DB    '║ Cc  46  2E │ Xx  45  2D │ /?  53  35 │'
  66.         DB    ' Ctrl 29  1D ║■'
  67.         DB    '║ Dd  32  20 │ Yy  21  15 │ \|  43  2B │'
  68.         DB    ' CpLk 58  3A ║■'
  69.         DB    '║ Ee  18  12 │ Zz  44  2C │ `~  41  29 │'
  70.         DB    ' LtSh 42  2A ║■'
  71.         DB    '║ Ff  33  21 │ 1!   2   2 │ SP  57  39 │'
  72.         DB    ' RtSh 54  36 ║■'
  73.         DB    '║ Gg  34  22 │ 2@   3   3 │ BS  14   E │'
  74.         DB    ' *PrS 55  37 ║■'
  75.         DB    '║ Hh  35  23 │ 3#   4   4 │ Tab 15   F │'
  76.         DB    ' Ins  82  52 ║■'
  77.         DB    '║ Ii  23  17 │ 4$   5   5 │ Esc  1   1 │'
  78.         DB    ' Del  83  53 ║■'
  79.         DB    '║ Jj  36  24 │ 5%   6   6 │ -   74  4A │'
  80.         DB    ' NmLk 69  45 ║■'
  81.         DB    '║ Kk  37  25 │ 6^   7   7 │ +   78  4E │'
  82.         DB    ' ScLk 70  46 ║■'
  83.         DB    '║ Ll  38  26 │ 7&   8   8 │ F1  59  3B │'
  84.         DB    ' Lt   75  4B ║■'
  85.         DB    '║ Mm  50  32 │ 8*   9   9 │ F2  60  3C │'
  86.         DB    ' Rt   77  4D ║■'
  87.         DB    '║ Nn  49  31 │ 9(  10   A │ F3  61  3D │'
  88.         DB    ' Up   72  48 ║■'
  89.         DB    '║ Oo  24  18 │ 0)  11   B │ F4  62  3E │'
  90.         DB    ' Dn   80  50 ║■'
  91.         DB    '║ Pp  25  19 │ -_  12   C │ F5  63  3F │'
  92.         DB    ' PgUp 73  49 ║■'
  93.         DB    '║ Qq  16  10 │ =+  13   D │ F6  64  40 │'
  94.         DB    ' PgDn 81  51 ║■'
  95.         DB    '║ Rr  19  13 │ [{  26  1A │ F7  65  41 │'
  96.         DB    ' Home 71  47 ║■'
  97.         DB    '║ Ss  31  1F │ ]}  27  1B │ F8  66  42 │'
  98.         DB    ' End  79  4F ║■'
  99.         DB    '║ Tt  20  14 │ ;:  39  27 │ F9  67  43 │'
  100.         DB    ' Pad5 76  4C ║■'
  101.         DB    '║ Uu  22  16 │ ',39,'"  40  28 │ F10 68  44 │'
  102.         DB    ' SCAN CODES  ║■'
  103.         DB    '╚════════════╧════════════╧════════════╧'
  104.         DB    '═════════════╝',0
  105.  
  106. FrameAtr    DB    70
  107. ChartAtr    DB    7
  108. VideoMode    DW    0            ;video mode number
  109. ColumnCount    DW    0            ;width of window in columns
  110. CursorPos    DW    0            ;cursor position
  111. SetupStatus    DB    0            ;indicates if window
  112.                         ; is already active
  113. PageNo        DW    0            ;current displayed page
  114. OldKbInt    LABEL    DWORD
  115. OldKeyboardInt    DW    2 DUP (0)        ;storage for old keyboard
  116. ResFlag        DB    0            ;memory resident flag
  117. MonoFlag    DB    0            ;monochrome only flag
  118.  
  119. ;---------------------------------------------------------------------------
  120. ;Execution comes here, to the main body of the program, when an interrupt 9
  121. ;is generated from the keyboard.  Registers are saved, then the keypress is
  122. ;checked and compared to the key combination that activates the menu window.
  123. ;This routine is only called if the SCANCODE is memory resident.
  124.  
  125. Main:        STI                ;enable software interrupts
  126.         PUSH    AX            ;save all registers
  127.         PUSH    BX
  128.         PUSH    CX
  129.         PUSH    DX
  130.         PUSH    SI
  131.         PUSH    DI
  132.         PUSH    DS
  133.         PUSH    ES
  134.         PUSH    AX            ;save AX for call to old
  135.                         ; routine
  136.         IN    AL,0A0h            ;re-enable NMI on PCjr
  137.         POP    AX            ;restore AX
  138.         PUSHF                ;simulate interrupt call to
  139.                         ; old keyboard routine
  140.         CALL    OldKbInt        ;call old routine
  141.         MOV    AH,2            ;check status of the shift
  142.                         ; keys
  143.         INT    16h
  144.         AND    AL,00000111b        ;Ctrl, Rt-Shift and Lt-Shift
  145.         CMP    AL,00000111b        ;depressed?
  146.         JE    DoProgram        ;if so, then skip exit routine
  147.  
  148. ;Exit routine is the common point of exit for all routines in the program.
  149.  
  150. Exit:        POP    ES
  151.         POP    DS
  152.         POP    DI
  153.         POP    SI
  154.         POP    DX
  155.         POP    CX
  156.         POP    BX
  157.         POP    AX
  158.         IRET
  159.  
  160. ;Execution comes here when the proper key combination, Ctrl/Rt-Shift, is
  161. ;pressed.  First task is to check whether or not the window is already open.
  162.  
  163. DoProgram:    PUSH    CS            ;set ES and DS to the code
  164.                         ; segment
  165.         POP    DS
  166.         PUSH    CS
  167.         POP    ES
  168.         CMP    SetupStatus,0        ;is the window already open?
  169.         JNE    Exit            ;yes, then ignore request
  170.  
  171. ;----------------------------------------------------------------------------
  172. ;Check current video mode.  If it's mode 2, 3, or 7, then set the window
  173. ;status flag, store the mode number and page number, save the cursor
  174. ;position.  If any other display mode is active instead, ignore the
  175. ;request and exit.
  176.  
  177.         CALL    GetMode            ;get page and mode numbers
  178.         CMP    AL,2            ;is crt now in an acceptable
  179.                         ; mode?
  180.         JE    Prog0            ;yes, then continue
  181.         CMP    AL,3
  182.         JE    Prog0
  183.         CMP    AL,7
  184.         JE    Prog0
  185.         JMP    Exit            ;no, then ignore request
  186. Prog0:        MOV    SetupStatus,1        ;set status flag to indicate
  187.                         ; that window is active
  188.         MOV    BL,BH            ;save page number for color
  189.                         ; displays
  190.         XOR    BH,BH
  191.         MOV    PageNo,BX
  192.  
  193. ;Start of code common to both memory resident and nonresident modes
  194.  
  195. DoNonResProg:    MOV    AH,3            ;get cursor position
  196.         INT    10h
  197.         MOV    CursorPos,DX        ;save it
  198.  
  199.         CALL    GetMode
  200.         CMP    AL,7            ;is it monochrome?
  201.         JE    Mono
  202.         CMP    MonoFlag,1        ;Monochrome override set?
  203.         JE    Mono
  204.  
  205.         MOV    FrameAtr,FrameColor    ;set screen colors
  206.         MOV    ChartAtr,ChartColor
  207.         JMP    SHORT Prog1
  208.  
  209. Mono:        MOV    FrameAtr,70h        ;set monochrome attributes
  210.         MOV    ChartAtr,7        ;normal video
  211.         CMP    ResFlag,1        ;if non-res, bypass screen
  212.         JNE    DisplayChart        ; save
  213.  
  214. ;Preparatory routines are completed.  Now open the window by first saving the
  215. ;contents of video memory beneath the window and then writing the window text
  216. ;directly to memory.
  217.  
  218. Prog1:        MOV    BX,PageNo        ;use BX as index into video
  219.                         ; segment address table
  220.         CALL    GetMode            ;get crt mode
  221.         CMP    AL,7
  222.         JNE    Prog2
  223.         MOV    BX,4            ;manually adjust index for
  224.                         ; monochrome adapter
  225. Prog2:        SHL    BX,1            ;multiply BX by two since
  226.                         ; table is made up of words
  227.         MOV    AX,Video[BX]        ;read segment from table
  228.         MOV    DS,AX            ;DS set to video memory
  229.         CALL    VideoDisable        ;turn display off
  230.         LEA    DI,WindowBuffer        ;set DI to buffer area to save
  231.                         ; screen contents
  232.         MOV    CX,3618h        ;54 columns 24 rows
  233.                         ; in the window
  234.         MOV    DX,000Dh        ;row 0 col 13
  235.                         ; upper left corner of window
  236.         CALL    Video2Mem        ;then transfer screen contents
  237.                         ; to buffer
  238. DisplayChart:    PUSH    DS            ;set ES to video memory
  239.         POP    ES
  240.         PUSH    CS            ;reset DS to code segment
  241.         POP    DS
  242.         LEA    SI,ScanData        ;print scan code chart
  243.         MOV    DX,000Dh        ;row 0 col 13
  244.         CALL    InsertString
  245.  
  246.         MOV    DX,1900h        ;move cursor off screen
  247.         CALL    Locate
  248.  
  249. GetKey:        XOR    AH,AH            ;get a keypress
  250.         INT    16h            ;BIOS keyboard input
  251.         CMP    AH,1            ;esc?
  252.         JNE    GetKey
  253.         CMP    ResFlag,1
  254.         JE    EscapeOut
  255.         MOV    DX,1700h
  256.         CALL    Locate
  257.         INT    20h
  258.  
  259. ;Execution comes here when the Esc key is pressed.  The window is refilled
  260. ;with its original contents, the cursor is restored, and control is handed
  261. ;back to the application program.
  262.  
  263. EscapeOut:    CALL    VideoDisable        ;turn off the display
  264.         LEA    SI,WindowBuffer        ;point to the buffer area
  265.                         ;define the window
  266.         MOV    CX,3618h        ;54 columns 24 lines
  267.         MOV    DX,000Dh        ;upper left corner
  268.                         ;row 0 col 13
  269.         CALL    Mem2Video        ;and write the buffer contents
  270.                         ; to the display
  271.         CALL    VideoEnable        ;turn display back on
  272.         MOV    DX,CursorPos        ;restore cursor position
  273.         CALL    Locate
  274.         CMP    ResFlag,0        ;is the program resident?
  275.         JNE    ResExit
  276.         INT    20h            ;if not, normal exit
  277.  
  278. ResExit:    MOV    SetupStatus,0        ;reset window status
  279.         JMP    Exit            ;and exit
  280.  
  281. ;-----------------------------------------------------------------------------
  282. ;Insert String Directly in the Video Buffer
  283. ;    SI string address    DX row, column
  284.  
  285. InsertString:    PUSH    ES
  286.         CALL    VideoDisable
  287.         CALL    CalcVidOffset        ;calc video offset
  288.         MOV    DI,AX            ;offset was returned in AX
  289.         CALL    SetVidAddr        ;set to monochrome or graphics
  290.         MOV    ES,AX            ;video buffer address into ES
  291.         MOV    AX,80            ;max chars per line
  292. InsertLoop:    MOV    DH,ChartAtr        ;set chart color
  293.         MOV    DL,BYTE PTR[SI]
  294.         CMP    DL,0
  295.         JE    InsertStrExit        ;exit if end of string
  296.         CMP    DL,0FEh            ;end of line marker?
  297.         JNE    InsertLoop2
  298.         SHL    AX,1            ;skip remaining positions on
  299.         ADD    DI,AX            ; this line
  300.         MOV    AX,80            ;and reset char count
  301.         JMP    SHORT NextByte
  302.  
  303. InsertLoop2:    CMP    DL,128
  304.         JB    InsertWord
  305.         MOV    DH,FrameAtr
  306.  
  307. InsertWord:    MOV    ES:WORD PTR[DI],DX    ;move char and attr to crt buf
  308.         ADD    DI,2            ;point to next crt buf loc
  309.         SUB    AX,1            ;dec available chars this line
  310. NextByte:    ADD    SI,1            ;point to next string byte
  311.         JMP    InsertLoop        ;move another word
  312.  
  313. InsertStrExit:    CALL    VideoEnable        ;video back on if CGA
  314.         POP    ES
  315.         RET
  316.  
  317. ;--------------------------------------------------------------------
  318. ;Direct Cursor Addressing
  319.  
  320. Locate:        PUSH    BX
  321.         MOV    AH,2            ;request move cursor
  322.         MOV    BX,PageNo        ;get active page no.
  323.         MOV    BH,BL
  324.         INT    10h
  325.         POP    BX
  326.         RET
  327.  
  328. ;---------------------------------------------------------------------------
  329. ;Video2Mem routine transfers the contents of a portion of video memory
  330. ;to a memory buffer for storage.
  331. ;Entry:        DS    - video segment
  332. ;        ES:DI    - memory buffer
  333. ;        DH,DL    - row and column of upper left corner of window
  334. ;        CH    - width of window in columns
  335. ;        CL    - number of lines in window
  336.  
  337. Video2Mem:    MOV    AL,CH            ;store number of columns
  338.         XOR    AH,AH
  339.         MOV    ColumnCount,AX
  340.         XOR    CH,CH            ;CX = number of lines
  341.         PUSH    DI            ;save DI
  342.         CALL    CalcVidOffset        ;get cell address of first
  343.                         ; character
  344.         MOV    SI,DI            ;put it in SI
  345.         POP    DI            ;restore DI
  346. Video2Mem1:    PUSH    SI            ;save SI for next line
  347.         PUSH    CX            ;save line count
  348.         MOV    CX,ColumnCount        ;set CX for call to WriteLn
  349.         CALL    WriteLn            ;transfer one line
  350.         POP    CX            ;restore saved registers
  351.         POP    SI
  352.         ADD    SI,160            ;set next line start address
  353.         LOOP    Video2Mem1        ;loop until all lines are done
  354.         RET
  355.  
  356. ;---------------------------------------------------------------------------
  357. ;Mem2Video writes a selected area of memory to the video display.
  358. ;Entry:        DS:SI    - memory buffer
  359. ;        ES    - video segment
  360. ;        DH,DL    - row and column of upper left corner of window
  361. ;        CH    - width of window in columns
  362. ;        CL    - number of lines in window
  363.  
  364. Mem2Video:    MOV    AL,CH            ;save number of columns
  365.         XOR    AH,AH
  366.         MOV    ColumnCount,AX
  367.         XOR    CH,CH            ;CX = number of lines
  368.         CALL    CalcVidOffset        ;get offset into video memory
  369. Mem2video1:    PUSH    DI            ;save video starting address
  370.         PUSH    CX            ;save line count
  371.         MOV    CX,ColumnCount        ;set CX for call to WriteLn
  372.         CALL    WriteLn            ;transfer one line
  373.         POP    CX            ;restore registers
  374.         POP    DI
  375.         ADD    DI,160            ;set DI for next display line
  376.         LOOP    Mem2video1        ;loop until done
  377.         RET
  378.  
  379. ;---------------------------------------------------------------------------
  380. ;WriteLn subroutine copies a string of words from one memory location to
  381. ;another.  The CGA status port is not checked for vertical retrace status
  382. ;before transfer.
  383. ;Entry:        DS:SI    - source
  384. ;        ES:DI    - destination
  385. ;        CX    - number of words
  386.  
  387. WriteLn:    CLD                ;clear for string instructions
  388. Write1:        MOVSW                ;move one word
  389.         LOOP    Write1            ;loop until done
  390.         RET
  391.  
  392. ;--------------------------------------------------------------------
  393. ;Get Video Mode.
  394. ;Returns CRT mode in AL and the number of character columns on the
  395. ;screen in AH.
  396.  
  397. GetMode:    MOV    AH,15            ;get page and mode numbers
  398.                         ;AL=mode, BH=page
  399.         INT    10h            ;BIOS video request
  400.         XOR    AH,AH
  401.         MOV    VideoMode,AX
  402.         RET
  403.  
  404. ;--------------------------------------------------------------------
  405. ;Set Video Address
  406.  
  407. SetVidAddr:    CALL    GetMode
  408.         CMP    AL,7            ;is it monochrome
  409.         JNE    ItsGraphics
  410.         MOV    AX,MonoSegAddr        ;monochrome buffer seg addr
  411.         RET
  412.  
  413. ItsGraphics:    MOV    AX,GraphSegAddr        ;graphics buffer seg address
  414.         RET
  415.  
  416. ;--------------------------------------------------------------------
  417. ;Calculate Video Address
  418. ;Entry:        DH,DL    - row and column of cell (0-24,0-79)
  419. ;Exit:        DI    - offset address
  420.  
  421. CalcVidOffset:    MOV    AX,160            ;number of bytes in row
  422.         MUL    DH            ;row * 160
  423.         SHL    DL,1            ;column * 2
  424.         XOR    DH,DH            ;byte to word
  425.         ADD    AX,DX            ;(row *160)+(column*2)
  426.         MOV    DI,AX            ;set offset in DI
  427.         RET
  428.  
  429. ;---------------------------------------------------------------------------
  430. ;VideoEnable and VideoDisable routines manipulate bit 3 of port 3D8h,
  431. ;the CGA Mode Control Register, to temporarily turn the display on or off.
  432. ;These routines write directly to hardware, and have no effect on other
  433. ;video adapters.
  434.  
  435. VideoDisable:    PUSH    DX
  436.         CMP    VideoMode,7        ;skip disable if in mode 7
  437.         JE    Disable2
  438.         MOV    DX,3DAh            ;read CGA status port
  439. Disable1:    IN    AL,DX            ;wait for vertical retrace to
  440.                         ;occur
  441.         TEST    AL,8            ;is bit 3 set?
  442.         JE    Disable1        ;no, wait until it is
  443.         MOV    DX,3D8h            ;now disable the display
  444.         MOV    AL,25h            ;by clearing bit 3 of the Mode
  445.                         ; Control Register
  446.         OUT    DX,AL
  447. Disable2:    POP    DX
  448.         RET
  449. ;    -    -    -    -    -    -    -    -    -
  450. VideoEnable:    CMP    VideoMode,7        ;skip enable if in mode 7
  451.         JE    Enable2
  452.         MOV    DX,3D8h            ;CGA Mode Control Register
  453.         MOV    BX,VideoMode        ;get re-enable display value
  454.         SUB    BX,2
  455.         MOV    AL,DisplayTable[BX]
  456.         OUT    DX,AL            ;and send it to the port
  457. Enable2:    RET
  458.  
  459. ;----------------------------------------------------------------------------
  460. ;This area is used to store the contents of the screen that underlies the
  461. ;window when the window is called up.  It overwrites the initialization
  462. ;code, since it is not needed after the program is started.
  463.  
  464. WindowBuffer    EQU    $
  465. BuffEnd        EQU    $+2592
  466. ;---------------------------------------------------------------------------
  467. ;Print hard copy of scancode chart
  468.  
  469. PrintChart:    LEA    SI,ScanData
  470.         JMP    SHORT CRLFnMargin
  471.  
  472. PrintLoop:    LODSB
  473.         CMP    AL,0
  474.         JE    PrintDone
  475.         CMP    AL,0FEh
  476.         JE    CRLFnMargin
  477.         MOV    DL,AL
  478.         MOV    AH,5
  479.         INT    21h
  480.         JMP    PrintLoop
  481.  
  482. ;Print CR & LF followed by margin for next line
  483.  
  484. CRLFnMargin:    PUSH    SI
  485.         LEA    SI,CRLFnMarginDat
  486. CRLFnLoop:    LODSB
  487.         CMP    AL,0
  488.         JZ    CRLFnMExit
  489.         MOV    DL,AL
  490.         MOV    AH,5
  491.         INT    21h
  492.         JMP    CRLFnLoop
  493.  
  494. CRLFnMExit:    POP    SI
  495.         JMP    PrintLoop
  496.  
  497. PrintDone:    MOV    DL,0Ch            ;send final formfeed
  498.         MOV    AL,5
  499.         INT    21h
  500.         INT    20h            ;all done
  501.  
  502. ;---------------------------------------------------------------------------
  503. ;Data used only by printer or help display
  504.  
  505. CRLFnMarginDat    DB    0Dh,0Ah,13 DUP (' '),0
  506.  
  507. HelpScreenDat:    DB    'Useage:■■'
  508.         DB    'SCANCODE [?HMPR]■■'
  509.         DB    '? or H  This help screen■'
  510.         DB    'M       Mono (for composite)■'
  511.         DB    'P       Printer only (IBM Character set required)■'
  512.         DB    'R       Go memory Resident■',0
  513.  
  514. ;---------------------------------------------------------------------------
  515. ClearScreen:    MOV    AX,0600h        ;scroll active page
  516.         MOV    BH,7            ;normal screen attribute
  517.         XOR    CX,CX            ;upper left
  518.         MOV    DX,184Fh        ;lower right
  519.         INT    10h            ;call BIOS
  520.         RET
  521. ;---------------------------------------------------------------------------
  522. ;Print instructions if flags ? or H are found
  523.  
  524. HelpScreen:    CALL    GetMode            ;store mode
  525.         CALL    ClearScreen
  526.         MOV    DX,0800h        ;row 8 col 0
  527.         LEA    SI,HelpScreenDat
  528.         CALL    InsertString
  529.         MOV    DX,1700H        ;row 23 col 0
  530.         CALL    Locate
  531.         INT    20h
  532. ;---------------------------------------------------------------------------
  533. ;Initialization routine checks the command line for switches.  If resident
  534. ;switch is set, saves and replaces the old keyboard interrupt vector.
  535.  
  536. Initialize:    ASSUME    DS:Code,ES:Code
  537.  
  538.         MOV    DX,80h            ;point to command line tail
  539.         MOV    SI,DX
  540.         MOV    DL,[SI]
  541.         CMP    DL,2            ;no tail?
  542.         JB    NonRes            ;if so, run nonresident mode
  543.         INC    SI            ;skip separator
  544. ComTailLoop:    INC    SI
  545.         MOV    DL,[SI]
  546.         CMP    DL,'?'
  547.         JE    HelpScreen
  548.         AND    DL,5Fh            ;mask to upper case
  549.         CMP    DL,'H'
  550.         JE    HelpScreen
  551.         CMP    DL,'P'            ;print flag?
  552.         JNE    CheckMono
  553.         JMP    PrintChart        ;print hard copy
  554.  
  555. CheckMono:    CMP    DL,'M'            ;switch for monochrome only?
  556.         JNE    CheckResSwitch
  557.         MOV    MonoFlag,1        ;if so, set flag
  558. CheckResSwitch:    CMP    DL,'R'            ;switch for TSR?
  559.         JNE    NextChar
  560.         MOV    ResFlag,1        ;if so, set flag
  561. NextChar:    CMP    DL,0Dh            ;return?
  562.         JNE    ComTailLoop        ;if not, check next char
  563.  
  564.         CMP    ResFlag,1        ;resident flag set?
  565.         JE    GoResident
  566. NonRes:        CALL    ClearScreen
  567.         JMP    DoNonResProg
  568.  
  569. ;Save the old keyboard interrupt vector and replace it with the new one.
  570.  
  571. GoResident:    MOV    AX,Interrupts        ;set DS to the interrupt
  572.                         ; vector area
  573.         MOV    DS,AX
  574.         ASSUME    DS:Interrupts
  575.         MOV    AX,KeyboardInt        ;save old vector
  576.         MOV    OldKeyboardInt,AX
  577.         MOV    AX,KeyboardInt[2]
  578.         MOV    OldKeyboardInt[2],AX
  579.         CLI                ;disable all interrupts but
  580.                         ; NMI
  581.         MOV    KeyboardInt,OFFSET Main ;and install new vector
  582.         MOV    KeyboardInt[2],CS
  583.         STI                ;re-enable interrupts
  584.         MOV    DX,OFFSET BuffEnd+1    ;point DX to end of resident
  585.                         ; section
  586.         INT    27h            ;terminate-but-stay-resident
  587.  
  588. Code        ENDS
  589.         END    Begin
  590.